﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Mvc;

using ProjectBase.Core;
using ProjectBase.Core.Dao;
using ProjectBase.Core.Service;

namespace $safeprojectname$
{
    [AttributeUsage(AttributeTargets.Method)]
    public class TransactionAttribute : ActionFilterAttribute, IExceptionFilter
    {
        #region IExceptionFilter Members
        public void OnException(ExceptionContext filterContext)
        {
            NHSessionRollback(filterContext);
            DbSessionRollback(filterContext);
            XmlSessionRollback(filterContext);
        }
        #endregion

        #region NHibernate
        protected virtual void NHSessionCommit(ActionExecutedContext filterContext)
        {
            var controller = filterContext.Controller as ICoreController<ICoreModel>;
            if (controller.Is())
            {
                var model = controller.Model;
                if (filterContext.Exception.IsNull()
                    && model.Is()
                    && (model.Messages.IsNull() || !model.Messages.ContainsError()))
                {
                    try // the last place where to check Exception
                    {
                        NHSession.TransactionCommit();
                        return;
                    }
                    catch (Exception ex)
                    {
                        controller.PublishFatal(ex);
                        // inform user about exception and rollback
                    }
                }
            }
            NHSession.TransactionRollback();
        }

        protected virtual void NHSessionRollback(ExceptionContext filterContext)
        {
            if (NHSession.TransactionIsActive)
            {
                NHSession.TransactionRollback();
            }
        }
        #endregion NHibernate

        #region DbSession
        protected virtual void DbSessionCommit(ActionExecutedContext filterContext)
        {
            if (!DbSession.TransactionIsActive)
            {
                return;
            }
            var controller = filterContext.Controller as ICoreController<ICoreModel>;
            if (controller.Is())
            {
                var model = controller.Model;
                if (filterContext.Exception.IsNull()
                    && model.Is()
                    && (model.Messages.IsNull() || !model.Messages.ContainsError()))
                {
                    try // the last place where to check Exception
                    {
                        DbSession.TransactionCommit();
                        return;
                    }
                    catch (Exception ex)
                    {
                        controller.PublishFatal(ex);
                        // inform user about exception and rollback
                    }
                }
            }
            DbSession.TransactionRollback();
        }

        protected virtual void DbSessionRollback(ExceptionContext filterContext)
        {
            if (DbSession.TransactionIsActive)
            {
                DbSession.TransactionRollback();
            }
        }
        #endregion DbSession

        #region XmlSession
        protected virtual void XmlSessionCommit(ActionExecutedContext filterContext)
        {
            if (!XmlSession.TransactionIsActive)
            {
                return;
            }
            var controller = filterContext.Controller as ICoreController<ICoreModel>;
            if (controller.Is())
            {
                var model = controller.Model;
                if (filterContext.Exception.IsNull()
                    && model.Is()
                    && (model.Messages.IsNull() || !model.Messages.ContainsError()))
                {
                    try // the last place where to check Exception
                    {
                        XmlSession.TransactionCommit();
                        return;
                    }
                    catch (Exception ex)
                    {
                        controller.PublishFatal(ex);
                        // inform user about exception and rollback
                    }
                }
            }
            XmlSession.TransactionRollback();
        }

        protected virtual void XmlSessionRollback(ExceptionContext filterContext)
        {
            if (XmlSession.TransactionIsActive)
            {
                XmlSession.TransactionRollback();
            }
        }
        #endregion XmlSession

        /// <summary>
        ///     Initiate the transaction.
        ///     Only for ICoreController
        /// </summary>
        /// <param name = "filterContext"></param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var controller = filterContext.Controller as ICoreController<ICoreModel>;
            if (controller.Is())
            {
                NHSession.TransactionBegin();
                DbSession.TransactionBegin();
                XmlSession.TransactionBegin();
            }
        }

        /// <summary>
        ///     Commits Transaction if TempData contains NO row only.
        ///     Any other case will Rollback changes
        /// </summary>
        /// <param name = "filterContext"></param>
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            NHSessionCommit(filterContext);
            DbSessionCommit(filterContext);
            XmlSessionCommit(filterContext);
        }

        #region session providers
        INHSessionHandler _nhSession;
        protected virtual INHSessionHandler NHSession
        {
            get { return _nhSession ?? (_nhSession = Factory.CreateInstance<INHSessionHandler>()); }
        }
        IDbSessionHandler _dbSession;
        protected virtual IDbSessionHandler DbSession
        {
            get { return _dbSession ?? (_dbSession = Factory.CreateInstance<IDbSessionHandler>()); }
        }
        IXmlSessionHandler _xmlSession;
        protected virtual IXmlSessionHandler XmlSession
        {
            get { return _xmlSession ?? (_xmlSession = Factory.CreateInstance<IXmlSessionHandler>()); }
        }
        #endregion session providers
    }
}